import numpy as np
from sklearn import datasets, preprocessing
from sklearn.model_selection import train_test_split
from neupy import algorithms
import pandas as pd
from hpelm import ELM
from sklearn.preprocessing import MinMaxScaler
from pylab import *
import numpy
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import r2_score


def transfer_Data(file_name):
    dat = pd.read_csv(file_name)
    x = dat.loc[:, [x for x in dat.columns.tolist() if x not in ('NEE')]].values
    y = np.array(dat.NEE)
    train_size = int(len(dat) * 0.75)
    return x, y, train_size


def scaler_for_data(x, y, scaler_for_x, scaler_for_y):
    x_scaler = scaler_for_x.fit_transform(x)
    y_scaler = scaler_for_y.fit_transform(y.reshape(-1, 1))
    return x_scaler, y_scaler


def inverse_transform(y, scaler_for_y):
    y_true = scaler_for_y.inverse_transform(y.reshape(-1, 1))
    return y_true


def RMSE(y_true, y_predict):
    return np.sqrt(((y_true - y_predict) ** 2).mean())


def MAE(y_true, y_predict):
    return np.abs((y_true - y_predict)).mean()


def score_R2(ans, y_test):
    pmean = np.mean(y_test)
    omean = np.mean(ans)
    SSR = 0.0
    varp = 0.0
    varo = 0.0
    for i in range(0, len(y_test)):
        diffXXbar = y_test[i] - pmean
        difYYbar = ans[i] - omean
        SSR += (diffXXbar * difYYbar)
        varo += diffXXbar ** 2
        varp += difYYbar ** 2
    SST = math.sqrt(varo * varp)
    return (SSR / SST) ** 2


def IA(s, o):
    ia = 1 -(np.sum((o-s)**2))/(np.sum((np.abs(s-np.mean(o))+np.abs(o-np.mean(o)))**2))
    return ia


scaler_for_x = MinMaxScaler(feature_range=(0, 1))
scaler_for_y = MinMaxScaler(feature_range=(0, 1))
x, y, train_size = transfer_Data("GF-Guy_HH_TOTAL.csv")
x_scaler, y_scaler = scaler_for_data(x, y, scaler_for_x, scaler_for_y)
x_train = x_scaler[:train_size, :]
y_train = y_scaler[:train_size]
x_test = x_scaler[train_size:, :]
y_test = y_scaler[train_size:]

# dataset = datasets.load_diabetes()
# x_train, x_test, y_train, y_test = train_test_split(
#      preprocessing.minmax_scale(dataset.data),
#      preprocessing.minmax_scale(dataset.target.reshape(-1, 1)),
#      test_size=0.3,)

nw = algorithms.GRNN(std=0.5, verbose=False)
nw.train(x_train, y_train)

def STEP_PREDICT(x, step = 1000):
    y_total = None
    for i in range(0, len(x), step):
        y = nw.predict(x[i:i + step])
        if y_total is None:
            y_total = y
        else:
            y_total = np.concatenate((y_total, y), axis=0)
    return y_total

predict_test = STEP_PREDICT(x_test)
predict_train = STEP_PREDICT(x_train)

predict_test = inverse_transform(predict_test, scaler_for_y)
predict_train = inverse_transform(predict_train, scaler_for_y)

train_true = inverse_transform(y_train, scaler_for_y)
test_true = inverse_transform(y_test, scaler_for_y)

train_rmse = RMSE(train_true, predict_train)
test_rmse = RMSE(test_true, predict_test)
print("train_rmse:", train_rmse)
print("test_rmse:", test_rmse)
train_rmse = MAE(train_true, predict_train)
test_rmse = MAE(test_true, predict_test)
print("train_mae:", train_rmse)
print("test_mae:", test_rmse)
train_r2 = score_R2(predict_train,train_true)
test_r2 = score_R2(predict_test,test_true)
print("train_r2:", train_r2)
print("test_r2:", test_r2)
train_ia = IA(predict_train,train_true)
test_ia = IA(predict_test,test_true)
print("train_ia:", train_ia)
print("test_ia:", test_ia)

true_list = numpy.array(numpy.concatenate((train_true, test_true)))
pred_list = numpy.array(numpy.concatenate((predict_train, predict_test)))

print("true_list: " + str(list(true_list.squeeze())))
print("pred_list: " + str(list(pred_list.squeeze())))

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(range(len(true_list)), true_list, c="black")
ax.plot(range(len(pred_list)), pred_list, c="red")
x_ticks = ax.set_xticks(range(len(true_list) / 24, len(true_list), len(true_list) / 12))
x_labels = ax.set_xticklabels(range(1, 13, 1), fontsize="small")
ax.set_xlabel("Month")
ax.set_ylabel("NEE(gCO2 m-2 d-1)")
ax.legend()
plt.show()